/*
 * Copyright 2006 - Chris Maki
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.theserverside.blog.dao;

import java.io.Serializable;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.NonUniqueResultException;

import com.theserverside.blog.dao.QueryParameter.TemporalType;

/**
 * A generic DAO interface that defineds the basic CRUD (Create, Retrieve,
 * Update, and Delete) operations used for most domain model objects.
 * 
 */

public interface GenericDao<T, PK extends Serializable> {
	/**
	 * Finds the instance of <code>T</code> identified by <code>pk</code>
	 * 
	 * @param pk
	 * @return
	 */
	public T findByPk(PK pk);

	/**
     * Find all instances of <code>T</code> in the database
     * 
     * @return a list <code>T</code> objects
     */
    public List<T> findAll();

    public List<T> find(String query);
    public List<T> find(String query, Object value);
    public List<T> find(String query, String name, Object value);
    public List<T> findPositionalParameter(String query, QueryParameter... args);
    public List<T> findNamedParameter(String query, NamedQueryParameter... args);
    
    public List<T> findByNamedQuery(String queryName);
    public List<T> findByNamedQueryNamedParameter(String queryName, String name, Object value);
    public List<T> findByNamedQueryNamedParameter(String queryName, String name, Object value, TemporalType type);
    /**
     * Find instances of <code>T</code> that match the criteria defined by
     * query <code>queryName</code>. <code>args</code> provide the values
     * for any named parameters in the query identified by
     * <code>queryName</code>.
     * 
     * @param queryName the named query to execute
     * @param args the values used by the query
     * @return a list of <code>T</codE> objects
     */
    public List<T> findByNamedQueryNamedParameter(String queryName, NamedQueryParameter... args);

    /**
     * 
     * Find instances of <code>T</code> that match the criteria defined by
     * query <code>queryName</code>. <code>args</code> provide values for
     * positional arguments in the query identified by <code>queryName</code>.
     * 
     * @param queryName the named query to execute
     * @param args the positional values used in the query
     * @return a list of <code>T</code> objects
     */
    public List<T> findByNamedQueryPositionalParameter(String queryName, QueryParameter... args);

    /**
	 * Find a single instance of <code>T</code> using the query named
	 * <code>queryName</code> and the arguments identified by
	 * <code>args</code>
	 * 
	 * @param queryName the name of the query to use
	 * @param args the arguments for the named query
	 * @return T or null if no objects match the criteria
	 * @throws NonUniqueResultException if more than one instance is returned.
	 */
    public T findInstanceByNamedQuery(String queryName);
    public T findInstanceByNamedQueryNamedParameter(String queryName, NamedQueryParameter... args);
    public T findInstanceByNamedQueryPositionalParameter(String queryName, QueryParameter... args);
   

    /**
     * Store <code>object</code> in the database.
     * 
     * @param object the instance to save in the database
     * @return the object stored in the database
     */
    public void persist(Object object);

    /**
     * 
     * @param object
     */
    public Object merge(Object object);

    /**
     * Remove <code>object</code> from the database.
     * 
     * @param object the object to be removed from the database
     */
    public void remove(Object object);

    // JPA support methods
    /**
     * Taken from the EntityManager documentation, Synchronize the persistence
     * context to the underlying database.
     * 
     */
    public void flush();
    
    /**
     * Taken from the EntityManager documentation: Clear the persistence
     * context, causing all managed entities to become detached. Changes made to
     * entities that have not been flushed to the database will not be
     * persisted.
     *
     */
    public void clear();
    
    public EntityManager getEntityManager();
    
            
}
